

#include "fq.h"
#include "list.h"
#include "heap_4.h"
#include "tls.h"


/*
    Fast queue.
    Characteristic:
    * Fast queue can automatically expansion space.
    * This can insert any type item.
    * Fast queue can use any where.
*/

/* Mix save list */
List_t xFqList;

/* list pointer */
List_t* pxFqList = NULL;

/**
* @fn  
* @brief 
* @param   
* @return   */
void FqInit(void)
{
    /* Create list */
	vListInitialise(&xFqList);

	/* point for list */
	pxFqList = &xFqList;
}

/**
* @fn  
* @brief insert items to queue
* @param   
* @return   */
void FqWrite(uint8 ucAttr , void *pxBuf , uint32 ulSize )
{
    uint16 usTtlSize;
    uint8 *pcSpace ;
    ListItem_t* pxListitem    = NULL;
    /* List item length. */
    uint8  ucOfsListItem = tlsAlignSizeGet(sizeof(ListItem_t)) ;

    /* calculation total size.
       ItemSize + [4byte] + [buffer length] */
	usTtlSize = ucOfsListItem + sizeof(uint32) + tlsAlignSizeGet(ulSize);

    /* Content buffer. */
    pxListitem = osal_mem_alloc(usTtlSize);

    if(pxListitem != NULL){

       /* Add attribute value  */
	   pxListitem->xItemValue = ucAttr;

       /* Content buffer. */
       pcSpace = (uint8*)pxListitem;
       
       /* Container buffer. */
       pxListitem->pvOwner = &pcSpace[ucOfsListItem];

       /* Write lenght to buffer. */
       memcpy(&pcSpace[ucOfsListItem] , &ulSize , sizeof(uint32) );

      /* Write buffer to buffer. */
       memcpy(&pcSpace[ucOfsListItem + sizeof(uint32)] ,pxBuf , ulSize);

       /* Inset list.(FIFO) */
	   vListInsert(pxFqList , pxListitem);
    }else{
        LOG("%s:insufficient space \r\n" , __FUNCTION__);
    }
}

/**
* @fn  
* @brief Find nearest item for attribute = ucAttr
* @param   
* @return   */
ListItem_t* prvFind(uint8 ucAttr)
{
    uint16 usNfItem = 0;
    ListItem_t* pxListitem = NULL;

    /* Get number of items in list. */
    usNfItem = listCURRENT_LIST_LENGTH(pxFqList);

    if(usNfItem == 0 ){
        return pxListitem;
    }else{

        /* Get first item. */
        pxListitem = listGET_HEAD_ENTRY(pxFqList) ;

        while(usNfItem--){
            /* FIFO return attribute first input item. */
            if(pxListitem->xItemValue == ucAttr){
                return pxListitem ;
            }else{
                pxListitem = listGET_NEXT(pxFqList);
            }
        }
    }

    return NULL ;
}

/**
* @fn  
* @brief 
* @param   
* @return   */
uint32 FqRead(uint8 ucAttr , void *pxBuf)
{
    uint32 pulSize = 0  ;
    uint8 *pcBuf;
    ListItem_t* pxListitem = prvFind(ucAttr) ;


    if(pxListitem == NULL){
        return 0 ;
    }else{

        /* Get data block. */
        pcBuf = listGET_LIST_ITEM_OWNER(pxFqList) ;

        /* Get buffer size. */
        memcpy(&pulSize, pcBuf , sizeof(uint32));

        /* Get buffer content. */
        memcpy(pxBuf , &pcBuf[sizeof(uint32)], pulSize);

        /* delete from list. */
        uxListRemove(pxListitem);

        /* release from memory pool. */
        osal_mem_free(pxListitem);

        return pulSize ;
    }
}

/**
* @fn  
* @brief Delete all message.
* @param   
* @return   */
void FqCancel(void)
{
    uint16 usNfItem = 0;
    ListItem_t* pxListitem = NULL;

    /* Get number of items in list. */
    usNfItem = listCURRENT_LIST_LENGTH(pxFqList);

    if(usNfItem != 0){

        /* Get first item. */
        pxListitem = listGET_HEAD_ENTRY(pxFqList) ;

        while(usNfItem--){

             /* delete from list. */
            uxListRemove(pxListitem);

            /* release from memory pool. */
            osal_mem_free(pxListitem);

            pxListitem = listGET_NEXT(pxFqList);
        }
    }
}











